package com.lsh.oms.core.proxy.service;

import com.alibaba.fastjson.JSON;
import com.lsh.atp.api.model.base.Item;
import com.lsh.atp.api.model.base.ItemDc;
import com.lsh.atp.api.model.hold.HoldDetailQueryRequest;
import com.lsh.atp.api.model.hold.HoldDetailQueryResponse;
import com.lsh.atp.api.model.hold.HoldResponse;
import com.lsh.atp.api.model.inventory.RestoreInventoryRequest;
import com.lsh.atp.api.service.hold.IHoldDatailQueryRpcService;
import com.lsh.atp.api.service.inventory.IInventoryRestoreRpcService;
import com.lsh.oms.core.constant.AtpConstant;
import com.lsh.oms.core.constant.ReturnCode;
import com.lsh.oms.core.exception.BusinessException;
import com.lsh.oms.core.model.order.AtpHoldDetail;
import com.lsh.oms.core.model.order.OrderDetail;
import com.lsh.oms.core.model.order.OrderHead;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author panxudong
 * @date 17/3/27
 */
@Component
public class AtpProxy {

    private static Logger logger = LoggerFactory.getLogger(AtpProxy.class);

    @Autowired
    private IInventoryRestoreRpcService restoreService;

    @Autowired
    private IHoldDatailQueryRpcService holdDatailQueryRPCService;

    public boolean restore(Long orderCode, boolean isFulfill, String logSign, Long venderId) {
        RestoreInventoryRequest request = new RestoreInventoryRequest();
        request.setChannel(AtpConstant.ATP_CHANNEL_CODE);
        request.setSequence(orderCode.toString());
        request.setIsFulfill(isFulfill);
        request.setVenderId(venderId);

        String message = "[AtpProxy][" + logSign + "]";
        HoldResponse response;
        try {
            logger.info(message + "[start][Request params:" + JSON.toJSONString(request) + "]");
            response = restoreService.restoreInventory(request);
            logger.info(message + "[end][Response result:" + JSON.toJSONString(response) + "]");
        } catch (Exception e) {
            logger.error(message + "[error][Error message:" + e.getMessage() + "]");
            logger.error(e.getMessage(), e);
            return false;
        }

        return response.getStatus().intValue() == AtpConstant.ATP_SUCCESS_RESPONSE
                || response.getStatus().intValue() == AtpConstant.ATP_RESORTED_RESPONSE;
    }


    public boolean restore(Long parentorderCode, List<OrderDetail> childrenOrderDetails, boolean isFulfill, String logSign, Long venderId) {
        RestoreInventoryRequest request = new RestoreInventoryRequest();
        request.setChannel(AtpConstant.ATP_CHANNEL_CODE);
        request.setSequence(parentorderCode.toString());
        request.setIsFulfill(isFulfill);

        List<Item> items = new ArrayList<>();
        for (OrderDetail orderDetail : childrenOrderDetails) {
            Item item = new Item();

            item.setItemId(orderDetail.getSkuCode());
            item.setQty(orderDetail.getGoodsSaleUnit().multiply(orderDetail.getQuantity()));

            Integer providerId = JSON.parseObject(orderDetail.getDetailExt()).getInteger("providerId");
            item.setSupplyMarket(providerId);

            items.add(item);
        }
        request.setItems(items);
        request.setVenderId(venderId);
        String message = "[AtpProxy][" + logSign + "]";
        HoldResponse response;
        try {
            logger.info(message + "[start][Request params:" + JSON.toJSONString(request) + "]");
            response = restoreService.restoreInventory(request);
            logger.info(message + "[end][Response result:" + JSON.toJSONString(response) + "]");
        } catch (Exception e) {
            logger.error(message + "[error][Error message:" + e.getMessage() + "]");
            logger.error(e.getMessage(), e);
            return false;
        }

        return response.getStatus().intValue() == AtpConstant.ATP_SUCCESS_RESPONSE
                || response.getStatus().intValue() == AtpConstant.ATP_RESORTED_RESPONSE;
    }


    /**
     * 获取订单商品库存扣减信息{SKU编号,{DC,数量}}
     *
     * @param orderCode
     * @return
     */
    public Map<String, AtpHoldDetail> querySkuDcQtyMap(Long orderCode) {

        HoldDetailQueryResponse resp = this.getHoldDetails(orderCode);

        List<ItemDc> items = resp.getItems();
        if (CollectionUtils.isEmpty(items)) {
            return Collections.emptyMap();
        }

        Map<String, AtpHoldDetail> atpHoldDetailMap = new HashMap<>(4);
        for (ItemDc item : items) {
            Long skuCode = item.getItemId();
            Integer supply = item.getSupplyId();
            Integer market = item.getSupplyMarket();
            String dc = item.getDc();
            String supplyKey = supply + ":" + market + ":" + dc;
            AtpHoldDetail atpHoldDetail = atpHoldDetailMap.get(supplyKey);
            if (atpHoldDetail == null) {
                atpHoldDetail = new AtpHoldDetail();

                atpHoldDetail.setDc(item.getDc());
                atpHoldDetail.setSupplierOrg(supply);
                atpHoldDetail.setSupplierMarket(item.getSupplyMarket());
                List<Long> skuList = new ArrayList<>();
                skuList.add(skuCode);
                atpHoldDetail.setSkuCodes(skuList);

                atpHoldDetailMap.put(supplyKey, atpHoldDetail);

            } else {
                atpHoldDetail.getSkuCodes().add(skuCode);
            }
        }

        return atpHoldDetailMap;
    }


    /**
     * @param orderCode
     * @return
     */
    public HoldDetailQueryResponse getHoldDetails(Long orderCode) {
        HoldDetailQueryRequest req = new HoldDetailQueryRequest();
        req.setSequence(orderCode.toString());
        req.setChannel("1");
//        req.setSequenceType(orderClass);
        long start = System.currentTimeMillis();
        logger.info("IHoldDatailQueryRPCService-queryHoldDetail start... params:" + JSON.toJSONString(req));
        HoldDetailQueryResponse resp = holdDatailQueryRPCService.queryHoldDetail(req);
        long end = System.currentTimeMillis();
        logger.info("IHoldDatailQueryRPCService-queryHoldDetail end, cost[" + (end - start) + "]... result:" + JSON.toJSONString(resp));

        if (resp == null) {
            throw new BusinessException(ReturnCode.REQUEST_FAIL, "查询库存扣减信息失败");
        }

        return resp;
    }


    /**
     * 获取订单商品库存扣减信息{SKU编号,{DC,数量}}
     *
     * @param order
     * @return
     */
    public HoldDetailQueryResponse queryRuleQtyMap(Long atpCode, OrderHead order) {
        HoldDetailQueryRequest req = new HoldDetailQueryRequest();

        req.setSequence(atpCode.toString());
        req.setSequenceType(order.getOrderClass());
        req.setChannel("1");
        long start = System.currentTimeMillis();
        logger.info("IHoldDatailQueryRPCService-queryHoldDetail start... params:" + JSON.toJSONString(req));
        HoldDetailQueryResponse resp = holdDatailQueryRPCService.queryHoldDetail(req);
        long end = System.currentTimeMillis();
        logger.info("IHoldDatailQueryRPCService-queryHoldDetail end, cost[" + (end - start) + "]... result:" + JSON.toJSONString(resp));

        return resp;
    }

    /**
     * 获取订单商品库存扣减信息{SKU编号,{DC,数量}}
     *
     * @param orderCode 订单号
     * @return 库存扣减信息
     */
    public Map<Long, Map<String, BigDecimal>> querySkuDcQtyInfo(Long orderCode) {
        HoldDetailQueryRequest req = new HoldDetailQueryRequest();
        req.setSequence(orderCode.toString());
        //OMS请求扣减库存设置值
        req.setChannel("1");
        long start = System.currentTimeMillis();
        logger.info("IHoldDatailQueryRPCService-queryHoldDetail start... params:" + JSON.toJSONString(req));
        HoldDetailQueryResponse resp = holdDatailQueryRPCService.queryHoldDetail(req);
        long end = System.currentTimeMillis();
        logger.info("IHoldDatailQueryRPCService-queryHoldDetail end, cost[" + (end - start) + "]... result:" + JSON.toJSONString(resp));
        List<ItemDc> items = resp.getItems();
        if (CollectionUtils.isEmpty(items)) {
            return Collections.emptyMap();
        }
        Map<Long, Map<String, BigDecimal>> map = new HashMap<>(4);
        for (ItemDc item : items) {
            Long skuCode = item.getItemId();
            Map<String, BigDecimal> dcQty = map.get(skuCode);
            if (dcQty == null) {
                dcQty = new HashMap<>();
                map.put(skuCode, dcQty);
            }
            String dc = item.getDc();
            Integer supply = item.getSupplyId();
            Integer market = item.getSupplyMarket();
            dc = dc + ":" + market + ":" + supply;
            BigDecimal qty = dcQty.get(dc);
            if (qty == null) {
                qty = item.getQty();
            } else {
                qty = qty.add(item.getQty());
            }
            dcQty.put(dc, qty);
        }
        return map;
    }

}
